<?php

class AdminDBHelper extends BaseAdminDBHelper {

	/**
	 * Mint az ősosztály, de megengedi más nyelvi folderbe is a fordítás létrehozását.
	 * Ez akkor kell, ha vannak fordítások és folderezés is.
	 */
	public static function addArticleInFolder($siteId, $id, $langcode, $defaultType, $folderId, $defaultWorktitle = null, $defaultSubtype = null) {
		if (! is_null($folderId)) {
			// check is folder exists
			$folder = SiteDBHelper::getArticleFolder($folderId);
			if (is_null($folder)) {
				throw MissingTableRowException("Folder id=$folderId not exists while trying to save article.");
			} else if ($folder['site_id'] != $siteId) {
				throw new Exception("Add article failed, because site id=$siteId does not match with folder site, which is " . $folder['site_id']);
			}
		}
		// add article
		$id = AdminDBHelper::addArticle($siteId, $id, $langcode, $defaultType, $defaultWorktitle, $defaultSubtype);
		if (! is_null($folderId)) {
			// add connection to folder
			$data = array(
					'id_article' => $id,
					'id_folder' => $folderId,
					'langcode' => $langcode
			);
			GeneralDBHelper::addTableRow('articlefolder_article', $data);
		}
		return $id;
	}

	/**
	 * Egy nyelv eltűnt egy site-ról - banners alatt töröljük a folderét
	 *
	 * @param Event $event az event
	 * @param mixed $userParam ez null lesz...
	 */
	public static function SiteLangRemoved($event, $userParam) {
			
		$langcode = $event->param->get("langcode");
		if(is_null($langcode))
		{
			$msg = "langcode param missing! event:\n".print_r($event, true);
			Log::error($msg);
			MailHelper::sendAdminMail("event problem", $msg);
			return;
		}
		$siteId = $event->param->get("siteId");
		if(is_null($siteId))
		{
			$msg = "siteId param missing! event:\n".print_r($event, true);
			Log::error($msg);
			MailHelper::sendAdminMail("event problem", $msg);
			return;
		}
			
		Log::info("AdminDBHelper: event '$event->eventName' received, removing folder from banners");

		$errs = FileUtil::deleteDir(FileUtil::mergeAndNormalizePaths(SITES_BANNERS_FOLDER, $langcode));
		if(!empty($errs)) {
			$msg = "failed to remove language '$langcode' directory from banners folder, errors:\n- ".implode("\n- ", $errs);
			Log::error($msg);
			MailHelper::sendAdminMail("remove dir failed", $msg);
		}
	}


	/**
	 * Egy nyelv let egy site alatt - banners alatt csinálunk foldert
	 *
	 * @param Event $event az event
	 * @param mixed $userParam ez null lesz...
	 */
	public static function SiteLangAdded($event, $userParam) {
			
		$langcode = $event->param->get("langcode");
		if(is_null($langcode))
		{
			$msg = "langcode param missing! event:\n".print_r($event, true);
			Log::error($msg);
			MailHelper::sendAdminMail("event problem", $msg);
			return;
		}
		$siteId = $event->param->get("siteId");
		if(is_null($siteId))
		{
			$msg = "siteId param missing! event:\n".print_r($event, true);
			Log::error($msg);
			MailHelper::sendAdminMail("event problem", $msg);
			return;
		}
			
		Log::info("AdminDBHelper: event '$event->eventName' received, adding folder under banners");

		$success = @mkdir(FileUtil::mergeAndNormalizePaths(SITES_BANNERS_FOLDER, $langcode));
		if(!$success) {
			$msg = "failed to create language '$langcode' directory under banners folder, error: ".$php_errormsg;
			Log::error($msg);
			MailHelper::sendAdminMail("add dir failed", $msg);
		}
	}

	function _________box() {
	}


	/**
	 * Megkeresi az összes cikk azonosítót, ami ehhez a box-hoz mint tartalom társítva van
	 *
	 * @param $boxId
	 * @return hiba esetén null, amúgy az id-k tömbje
	 */
	public static function getContentArticleIdsOfBox($boxId)
	{
		$db = DBHandler::dbGet();

		$sql = "select b.id, bcl.id as bcl_id, bcl.name, bcl.box_article_ids from box b, box_tab bt, box_content_list bcl where b.id=$boxId and b.id=bt.box_id and bt.id = bcl.box_tab_id";
		$result =& $db->getAll($sql);

		if(PEAR::isError($result))
		{
			$msg = "failed to determine which box articles are connected to box id=$boxId due to db error ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);
				
			return null;
		}

		$articleIds = array();
		foreach($result as $record)
		{
			if(!empty($record['box_article_ids']))
			{
				$ids = unserialize($record['box_article_ids']);
				foreach($ids as $id)
				{
					if(!FunctionLibrary::arrayContains($articleIds, $id))
					array_push($articleIds, $id);
				}
			}
		}

		return $articleIds;
	}


	/**
	 * Adott doboz összes box_content_list cuccáról törli a cikkeket, de mást nem bánt!
	 *
	 * @param int $boxId melyik box?
	 * @return boolean true ha oké volt, hiba esetén false
	 */
	public static function clearAllContentArticlesfromBox($boxId)
	{
		$db = DBHandler::dbGet();

		$statement = $db->prepare("update box_content_list set box_article_ids=null where id in (select bcl.id from box b, box_tab bt, box_content_list bcl where b.id=? and b.id=bt.box_id and bt.id = bcl.box_tab_id)");
		$result =& $db->execute($statement, array($boxId));
			
		if(PEAR::isError($result))
		{
			$msg = "failed to clear box articles connections at box id=$boxId due to db error ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);
				
			return false;
		}

		return true;
	}

	/**
	 * Visszaadja a dobozt azonosító alapján.
	 *
	 * @param string $id Doboz azonosítója.
	 * @return array Doboz értékei.
	 */
	public static function &getBox($id) {
		return GeneralDBHelper::getTableRow('box', $id);
	}

	/**
	 * Visszaadja a legnagyobb sorszámú dobozt
	 *
	 * @param string $langCode Nyelvkód
	 * @return array Doboz legnagyobb sorszáma (ha nincs doboz, akkor 0).
	 */
	public static function getMaxBoxSerial($langCode, $place, $siteId, $isForward = true, $serial = null) {
		$db = DBHandler::dbGet();

		if (is_null($serial)) {
			if ($isForward) {
				$sql = "select * from box where langcode=? and site_id=? and place=? and serial = (select max(serial) from box where langcode=? and site_id=? and place=?)";
			} else {
				$sql = "select * from box where langcode=? and site_id=? and place=? and serial = (select min(serial) from box where langcode=? and site_id=? and place=?)";
			}
			$data = array($langCode, $siteId, $place, $langCode, $siteId, $place);
		} else {
			if ($isForward) {
				$sql = "select * from box where langcode=? and site_id=? and place=? and serial = (select max(serial) from box where langcode=? and site_id=? and place=? and serial<?)";
			} else {
				$sql = "select * from box where langcode=? and site_id=? and place=? and serial = (select min(serial) from box where langcode=? and site_id=? and place=? and serial>?)";
			}
			$data = array($langCode, $siteId, $place, $langCode, $siteId, $place, $serial);
		}
		$result =& $db->getRow($sql, $data);

		if(PEAR::isError($result))
		{
			$msg = "failed to get box record id=$id from db: ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);

			throw new Exception(TextHandler::getText("err_sql_error"));
		}
			
		if($result) {
			return $result;
		} else {
			return null;
		}
	}

	/**
	 * Egy új doboz hozzáadása a rendszerhez.
	 *
	 * @return int visszaadja a doboz $id-jét a végén ha sikerül a hozzáadás, nyelvesített exception hiba esetén
	 */
	public static function addBox($name, $langcode, $siteId, $newPlace = BOX_PLACE_LEFT)
	{
		if (empty($langcode)) {
			$langcode = AdminBase::getCurrentEditlang();
		}

		$otherRecord = AdminDBHelper::getMaxBoxSerial($langcode, $newPlace, $siteId);
		if (is_null($otherRecord)) {
			$nextSerial = 1;
		} else {
			$nextSerial = $otherRecord['serial'] + 1;
		}
		$defaultValues = array(
			'name' => $name,
			'place' => $newPlace,
			'langcode' => $langcode, 
			'serial' => $nextSerial,
			'site_id' => $siteId,
		);
		$db = DBHandler::dbGet();
		$db->autoCommit(false);
		try {
			$boxId = GeneralDBHelper::addTableRowInTransaction($db, 'box', $defaultValues);

			$defaultValues = array(
				'box_id' => $boxId,
				'label' => TextHandler::getText("bxt_defaultlabel"), 
				'isdefault' => true, 
				'serial' => 1
			);
			$boxTabId = GeneralDBHelper::addTableRowInTransaction($db, 'box_tab', $defaultValues);

			$db->commit();
			$db->autoCommit(true);

			// logoljuk
			Log::info("new box id=$boxId created");

			return $boxId;
		} catch (Exception $e) {
			$db->rollback();
			$db->autoCommit(true);
			throw $e;
		}
	}

	/**
	 * Törli a dobozt
	 *
	 * @param int $id
	 * @return void ha minden oké, nyelvesített exception ha nem
	 */
	public static function &delBox($id)
	{
		$db = DBHandler::dbGet();
		$db->autoCommit(false);
		try {
			$record =& GeneralDBHelper::delTableRowInTransaction($db, 'box', $id);

			$statement = $db->prepare("update box set serial = serial - 1 where langcode = ? and site_id = ? and place = ? and serial > ?");
			$data = array($record['langcode'], $record['site_id'], $record['place'], $record['serial']);
			$result =& $db->execute($statement, $data);

			if (PEAR::isError($result)) {
				$msg = "failed to delete box record from db, due unable to correct other record serials: ".$result->getDebugInfo();
				Log::error($msg);
				MailHelper::sendAdminMail("db error occured", $msg);

				throw new Exception(TextHandler::getText("err_sql_error"));
			}
			$db->commit();
			$db->autoCommit(true);

			return $record;
		} catch (Exception $e) {
			$db->rollback();
			$db->autocommit(true);
			throw $e;
		}
	}

	/**
	 * Doboz frissítése
	 *
	 * @param array $boxValuesObject db objektum vagy asszociatív tömb benne az értékekkel
	 * @return void ha minden oké, nyelvesített exception ha gáz va
	 */
	public static function &modBox($boxValuesObject)
	{
		if (empty($boxValuesObject['name'])) {
			throw new Exception(TextHandler::getText("bx_err_name_empty"));
		} else if (! is_numeric($boxValuesObject['height'])) {
			throw new Exception(TextHandler::getText("bx_err_height_wrongformat"));
		}

		return GeneralDBHelper::modTableRow('box', $boxValuesObject);
	}

	/**
	 * Doboz mozgatása
	 *
	 * @param array $boxValuesObject db objektum vagy asszociatív tömb benne az értékekkel
	 * @param boolean $isForward ha igaz, akkor előre mozgatja (csökken a sorszáma)
	 * @return void ha minden oké, nyelvesített exception ha gáz va
	 */
	public static function moveBox($boxValuesObject, $isForward = true)
	{
		$id = $boxValuesObject['id'];
		$serial = $boxValuesObject['serial'];
		$place = $boxValuesObject['place'];

		if (empty($id) || ! is_numeric($id)) {
			throw new Exception(TextHandler::getText("bx_err_id_missing"));
		} else if (empty($serial) || ! is_numeric($serial)) {
			throw new Exception(TextHandler::getText("bx_err_serial_missing"));
		}
		$otherRecord = AdminDBHelper::getMaxBoxSerial($boxValuesObject['langcode'], $place, $boxValuesObject['site_id'], $isForward, $serial);
		if (is_null($otherRecord)) {
			if ($isForward) {
				throw new Exception(TextHandler::getText("bx_err_serial_cantforward"));
			} else {
				throw new Exception(TextHandler::getText("bx_err_serial_cantbackward"));
			}
		}
		$db = DBHandler::dbGet();

		$db->autoCommit(false);
		try {
			if ($isForward) {
				$statement = $db->prepare('update box set serial = serial + 1 where id=?');
			} else {
				$statement = $db->prepare('update box set serial = serial - 1 where id=?');
			}
			$data = array($otherRecord['id']);
			$result =& $db->execute($statement, $data);
			if (PEAR::isError($result)) {
				throw new Exception();
			}

			if ($isForward) {
				$statement = $db->prepare('update box set serial = serial - 1 where id=?');
			} else {
				$statement = $db->prepare('update box set serial = serial + 1 where id=?');
			}
			$data = array($id);
			$result =& $db->execute($statement, $data);
			if (PEAR::isError($result)) {
				throw new Exception();
			}
			$result = $db->commit();

		} catch (Exception $e) {
			$result = $db->rollback();
		}
		$db->autoCommit(true);

		if (PEAR::isError($result))
		{
			$msg = "moving box record id=$id in db failed: ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);

			throw new Exception(TextHandler::getText("err_sql_error"));
		}
			
		Log::info("box record id=$id is moved to: ".print_r($boxValuesObject, true));
	}

	/* Doboz fülek */


	/**
	 * Visszaadja a doboz fület azonosító alapján.
	 *
	 * @param string $id Doboz fül azonosítója.
	 * @return array Doboz fül értékei.
	 */
	public static function &getBoxTab($id) {
		return GeneralDBHelper::getTableRow("box_tab", $id);
	}

	/**
	 * Visszaadja a legnagyobb doboz fül sorszámot
	 *
	 * @param int $boxId Doboz azonosítója
	 * @return array Doboz legnagyobb sorszáma (ha nincs doboz, akkor 0).
	 */
	public static function getMaxBoxTabSerial($boxId, $isForward = true, $serial = null) {
		$db = DBHandler::dbGet();

		if (is_null($serial)) {
			if ($isForward) {
				$sql = "select * from box_tab where box_id=? and serial = (select max(serial) from box_tab where box_id=?)";
			} else {
				$sql = "select * from box_tab where box_id=? and serial = (select min(serial) from box_tab where box_id=?)";
			}
			$data = array($boxId, $boxId);
		} else {
			if ($isForward) {
				$sql = "select * from box_tab where box_id=? and serial = (select max(serial) from box_tab where box_id=? and serial<?)";
			} else {
				$sql = "select * from box_tab where box_id=? and serial = (select min(serial) from box_tab where box_id=? and serial>?)";
			}
			$data = array($boxId, $boxId, $serial);
		}
		$result =& $db->getRow($sql, $data);

		if(PEAR::isError($result))
		{
			$msg = "failed to get box tab record id=$id from db: ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);

			throw new Exception(TextHandler::getText("err_sql_error"));
		}
			
		if($result) {
			return $result;
		} else {
			return null;
		}
	}


	public static function hasBoxAfter($boxRecord)
	{
		$db = DBHandler::dbGet();

		$sql = "select id from box where langcode=? and site_id=? and place=? and serial > ?";
		$data = array($boxRecord['langcode'], $boxRecord['site_id'], $boxRecord['place'], $boxRecord['serial']);
		$result =& $db->getRow($sql, $data);

		if(PEAR::isError($result))
		{
			$msg = "failed to get next box record from db: ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);

			throw new Exception(TextHandler::getText("err_sql_error"));
		}

		if($result)
		return true;
		else
		return false;
	}


	/**
	 * Egy új doboz fül hozzáadása a rendszerhez.
	 *
	 * @param int $boxId doboz azonosítója
	 * @return int visszaadja a doboz fül $id-jét a végén ha sikerül a hozzáadás, nyelvesített exception hiba esetén
	 */
	public static function &addBoxTab($boxId, $label)
	{
		$otherRecord = AdminDBHelper::getMaxBoxTabSerial($boxId);
		if (is_null($otherRecord)) {
			$nextSerial = 1;
		} else {
			$nextSerial = $otherRecord['serial'] + 1;
		}

		$data = array(
			"box_id" => $boxId,
			"label" => $label,
			"isdefault" => false,
			"serial" => $nextSerial
		);

		return GeneralDBHelper::addTableRow("box_tab", $data);
	}

	/**
	 * Egy új doboz fül alapértelmezetté tétele.
	 *
	 * @param int $boxId doboz azonosítója (a default fül felderítése miatt kell
	 * @param int $boxTabId doboz fül azonosítója
	 */
	public static function makeBoxTabDefault($boxTabId, $boxId)
	{
		$db = DBHandler::dbGet();
			
		$statement = $db->prepare('update box_tab set isdefault = not isdefault where (id = ? or isdefault) and box_id = ?');
		$data = array($boxTabId, $boxId);
		$result =& $db->execute($statement, $data);
			
		if (PEAR::isError($result))
		{
			$msg = "making box tab default id=$boxTabId to db failed: ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("making box tab default failed", $msg);
			throw new Exception(TextHandler::getText("err_sql_error"));
		}
		// logoljuk
		Log::info("made box tab id=$boxTabId default");
	}

	/**
	 * Törli a doboz fület
	 *
	 * @param int $id
	 * @return void ha minden oké, nyelvesített exception ha nem
	 */
	public static function &delBoxTab($id)
	{
		$db = DBHandler::dbGet();
		$db->autoCommit(false);
		try {
			$record =& GeneralDBHelper::delTableRowInTransaction($db, 'box_tab', $id);

			$statement = $db->prepare("update box_tab set serial = serial - 1 where box_id = ? and serial > ?");
			$data = array($record['box_id'], $record['serial']);
			$result =& $db->execute($statement, $data);

			if (PEAR::isError($result)) {
				$msg = "failed to delete box_tab record from db, due unable to correct other record serials: ".$result->getDebugInfo();
				Log::error($msg);
				MailHelper::sendAdminMail("db error occured", $msg);

				throw new Exception(TextHandler::getText("err_sql_error"));
			}
			$db->commit();
			$db->autoCommit(true);

			return $record;
		} catch (Exception $e) {
			$db->rollback();
			$db->autocommit(true);
			throw $e;
		}
	}

	/**
	 * Doboz fül frissítése
	 *
	 * @param array $boxTabValuesObject db objektum vagy asszociatív tömb benne az értékekkel
	 * @return void ha minden oké, nyelvesített exception ha gáz va
	 */
	public static function &modBoxTab($boxTabId, $boxContentListArray)
	{
		$db = DBHandler::dbGet();
		$db->autocommit(false);

		try {
			// $record =& GeneralDBHelper::modTableRowInTransaction($db, "box_tab", $boxTabValuesObject);

			foreach ($boxContentListArray as $boxContentList) {
				if (isset($boxContentList['isdeleted'])) {
					if (! isset($boxContentList['isnew'])) {
						// ezt törölni kell
						GeneralDBHelper::delTableRowInTransaction($db, 'box_content_list', $boxContentList['id']);
					}
				} else if (isset($boxContentList['isnew'])) {
					// új rekord, menteni kell
					unset($boxContentList['isnew']);
					unset($boxContentList['ismodified']);
					$boxContentList['box_article_ids'] = serialize($boxContentList['box_article_ids']);
					GeneralDBHelper::addTableRowInTransaction($db, "box_content_list", $boxContentList);
				} else if (isset($boxContentList['ismodified'])) {
					// módosított rekord
					unset($boxContentList['ismodified']);
					$boxContentList['box_article_ids'] = serialize($boxContentList['box_article_ids']);
					GeneralDBHelper::modTableRowInTransaction($db, 'box_content_list', $boxContentList);
				}
			}
			$db->commit();
			$db->autocommit(true);
			return $record;
		} catch (Exception $e) {
			$db->rollback();
			$db->autocommit(true);
			throw $e;
		}
	}

	/**
	 * Doboz fül mozgatása
	 *
	 * @param array $boxValuesObject db objektum vagy asszociatív tömb benne az értékekkel
	 * @param boolean $isForward ha igaz, akkor előre mozgatja (csökken a sorszáma)
	 * @return void ha minden oké, nyelvesített exception ha gáz va
	 */
	public static function moveBoxTab($boxTabValuesObject, $isForward = true)
	{
		$id = $boxTabValuesObject['id'];
		$serial = $boxTabValuesObject['serial'];

		if (empty($id) || ! is_numeric($id)) {
			throw new Exception(TextHandler::getText("bxt_err_id_missing"));
		} else if (empty($serial) || ! is_numeric($serial)) {
			throw new Exception(TextHandler::getText("bxt_err_serial_missing"));
		}
		$otherRecord = AdminDBHelper::getMaxBoxTabSerial($boxTabValuesObject['box_id'], $isForward, $serial);
		if (is_null($otherRecord)) {
			if ($isForward) {
				throw new Exception(TextHandler::getText("bxt_err_serial_cantforward"));
			} else {
				throw new Exception(TextHandler::getText("bxt_err_serial_cantbackward"));
			}
		}
		$db = DBHandler::dbGet();

		$db->autoCommit(false);
		try {
			if ($isForward) {
				$statement = $db->prepare('update box_tab set serial = serial + 1 where id=?');
			} else {
				$statement = $db->prepare('update box_tab set serial = serial - 1 where id=?');
			}
			$data = array($otherRecord['id']);
			$result =& $db->execute($statement, $data);
			if (PEAR::isError($result)) {
				throw new Exception();
			}

			if ($isForward) {
				$statement = $db->prepare('update box_tab set serial = serial - 1 where id=?');
			} else {
				$statement = $db->prepare('update box_tab set serial = serial + 1 where id=?');
			}
			$data = array($id);
			$result =& $db->execute($statement, $data);
			if (PEAR::isError($result)) {
				throw new Exception();
			}
			$result = $db->commit();

		} catch (Exception $e) {
			$result = $db->rollback();
		}
		$db->autoCommit(true);

		if (PEAR::isError($result))
		{
			$msg = "moving box_tab record id=$id in db failed: ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);

			throw new Exception(TextHandler::getText("err_sql_error"));
		}
			
		Log::info("box_tab record id=$id is moved to: ".print_r($boxTabValuesObject, true));
	}


	/**
	 * Visszaadja a megadott doboz alapérzelmezett doboz fülét.
	 *
	 * @param string $boxId doboz azonosítója
	 * @return array
	 */
	public static function &getDefaultBoxTab($boxId) {
		$filter = array("box_id" => $boxId, 'isdefault' => true);
		$defaultBoxTab =& GeneralDBHelper::getTableRowsFiltered('box_tab', $filter, null, 1);
		if (count($defaultBoxTab) > 0 && isset($defaultBoxTab[0]['id'])) {
			return $defaultBoxTab[0];
		} else {
			$nullValue = null;
			return $nullValue;
		}
	}

	/**
	 * Visszaadja a megadott doboz alapérzelmezett doboz fülének doboz tartalom listáját.
	 *
	 * @param string $boxId doboz azonosítója
	 * @return array
	 */
	public static function &getDefaultBoxContentLists($boxId) {
		$filter = array("box_id" => $boxId, 'isdefault' => true);
		$defaultBoxTab =& GeneralDBHelper::getTableRowsFiltered('box_tab', $filter, null, 1, array("id"));
		if (count($defaultBoxTab) > 0 && isset($defaultBoxTab[0]['id'])) {
			$records =& SiteDBHelper::getBoxContentLists($defaultBoxTab[0]['id']);
		} else {
			$msg = "failed to get default box tab for box id=$boxId";
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);
			throw new Exception(TextHandler::getText('err_db_consistency_error'));
		}
		return $records;
	}

	/**
	 * Visszaadja a doboz tartalom listát.
	 *
	 * @param string $boxTabId doboz tartalom lista azonosítója
	 * @return array
	 */
	public static function &getBoxContentList($boxContentListId) {
		$record = GeneralDBHelper::getTableRow("box_content_list", $boxContentListId);
		$record['box_article_ids'] = unserialize($record['box_article_ids']);
		return $record;
	}

	/**
	 * Egy új doboz tartalom lista hozzáadása a rendszerhez.
	 *
	 * @param string $boxTabId Doboz tartalom lista azonosítója
	 * @return int visszaadja a doboz tartalom lista $id-jét a végén ha sikerül a hozzáadás, nyelvesített exception hiba esetén
	 */
	public static function &generateBoxContentList($boxTabId, $name)
	{
		// nincs, kell egy új id
		$boxContentListId = DBUtil::getSeqValue("objectid");
		if($boxContentListId == -1)
		{
			$msg = "failed to get new objectid! Adding new box_content_list failed!";
			Log::error($msg);
			MailHelper::sendAdminMail("adding new box_content_list failed", $msg);

			throw new Exception(TextHandler::getText("err_sql_error"));
		}

		$boxContentListRecord = array(
			'id' => $boxContentListId,
			'box_tab_id' => $boxTabId,
			'name' => $name,
			'isdefault' => false,
			'box_article_ids' => array(),
			'class' => 'BoxContentList',
			'type' => BOXCONTENTLIST_DEFAULT_TYPE,
			'sizemin' => null,
			'sizemax' => null,
			'isnew' => true,
		);

		return $boxContentListRecord;
	}

	/**
	 * Egy új doboz tartalom lista hozzáadása a rendszerhez.
	 *
	 * @param string $boxContentListRecords Doboz tartalom lista értékei
	 * @return int visszaadja a doboz tartalom lista $id-jét a végén ha sikerül a hozzáadás, nyelvesített exception hiba esetén
	 */
	public static function &addBoxContentList($boxContentListRecords)
	{
		return GeneralDBHelper::addTableRow("box_content_list", $boxContentListRecords);
	}

	/**
	 * Egy doboz tartalom lista törlése.
	 *
	 * @param string $boxContentListId Doboz lista tartalom azonosítója
	 */
	public static function &delBoxContentList($boxContentListId)
	{
		return GeneralDBHelper::delTableRow("box_content_list", $boxContentListId);
	}

	/**
	 * Egy doboz tartalom lista módosítása.
	 *
	 * @param string $boxContentListRecord Doboz lista tartalom
	 */
	public static function &modBoxContentList($boxContentListRecord)
	{
		$boxContentListRecord['box_article_ids'] = serialize($boxContentListRecord['box_article_ids']);
		if (empty($boxContentListRecord['autostep'])) {
			$boxContentListRecord['autostep'] = null;
		}
		return GeneralDBHelper::modTableRow("box_content_list", $boxContentListRecord);
	}

	/**
	 * Egy doboz tartalmak lekérése.
	 *
	 * @param string $langcode Ehhez a nyelvhez
	 */
	public static function getBoxContents($langcode) {
		return SiteDBHelper::getArticles(SiteHandler::getCurrentSiteId(), $langcode, array(ARTICLE_TYPE_BOXCONTENT));
	}


	/**
	 * Visszaadja a dobozok és doboz fülek listáját.
	 *
	 * @param $langcode Ezen a nyelven
	 * @return array A lekérdezés eredménye
	 */
	public static function &getBoxTabFull($langcode = null, $orderBy = null) {
		if (is_null($langcode)) {
			$langcode = AdminBase::getCurrentEditlang();
		}
		if (is_null($orderBy)) {
			$orderBy = array('box_name asc', 'label asc');
		}
		$filter = array('langcode' => $langcode);
		return GeneralDBHelper::getTableRowsFiltered('vw_box_tab_list', $filter, $orderBy);
	}

	/**
	 * Visszaadja a dobozok, doboz fülek és doboz tartalmak listáját.
	 *
	 * @param $articleId Erre a cikkre vonatkozóan
	 * @param $langcode Ezen a nyelven
	 * @return array A lekérdezés eredménye
	 */
	public static function &getBoxContentListOverrideFull($articleId, $langcode = null, $orderBy = 'box_name asc, box_tab_label asc, name asc') {
		if (is_null($langcode)) {
			$langcode = AdminBase::getCurrentEditlang();
		}
		$db = DBHandler::dbGet();

		$sql = "select bcl.*, abc.article_id from vw_box_content_list bcl left join article_boxcontentlist_connect abc ON (bcl.id = abc.box_content_list_id and bcl.langcode = abc.langcode and abc.article_id = ?) where bcl.langcode = ? order by $orderBy";
		$data = array($articleId, $langcode);
		$result =& $db->getAll($sql, $data);

		if(PEAR::isError($result))
		{
			$msg = "failed to get article box content list override records from db: ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);

			throw new Exception(TextHandler::getText("err_sql_error"));
		}

		return $result;
	}

	/**
	 * A megadott cikkre a cikk - doboz tartalom lista kapcsolótábla adatait felülírja.
	 *
	 * @param $articleId Cikk azonosítója (törlés miatt kell)
	 * @param $updateArray Új kapcsolótábla értékek
	 */
	public static function updateArticleOverrideBoxContentList($articleId, $updateArray) {
		$db = DBHandler::dbGet();
		$db->autoCommit(false);
		try {
			$statement = $db->prepare("delete from article_boxcontentlist_connect where article_id=?");
			$data = array($articleId);
			$result =& $db->execute($statement, $data);

			if (PEAR::isError($result))
			{
				$msg = "removing article_boxcontentlist_connect records article_id=$articleId from db failed: ".$result->getDebugInfo();
				Log::error($msg);
				MailHelper::sendAdminMail("db error occured", $msg);
				throw new Exception(TextHandler::getText("err_sql_error"));
			}

			$langcode = AdminBase::getCurrentEditlang();
			foreach ($updateArray as $updateValue) {
				$statement = $db->prepare("insert into article_boxcontentlist_connect(article_id,box_content_list_id,langcode) values (?,?,?)");
				$data = array($updateValue['article_id'], $updateValue['box_content_list_id'], $langcode);
				$result =& $db->execute($statement, $data);
					
				if (PEAR::isError($result))
				{
					$msg = "insering article_boxcontentlist_connect article_id=".$updateValue['article_id'].",box_content_list_id=".$updateValue['box_content_list_id']." from db failed: ".$result->getDebugInfo();
					Log::error($msg);
					MailHelper::sendAdminMail("db error occured", $msg);
					throw new Exception(TextHandler::getText("err_sql_error"));
				}
			}
			$db->commit();
			$db->autoCommit(true);
		} catch (Exception $e) {
			$db->rollback();
			$db->autoCommit(true);
			throw $e;
		}
	}

	/**
	 * A megadott cikkre a cikk - doboz tartalom lista kapcsolótábla adatait kitörli.
	 *
	 * @param $articleId Cikk azonosítója
	 * @param $langcode Nyelv
	 * @param $updateArray Új kapcsolótábla értékek
	 */
	public static function delArticleOverrideBoxContentList($articleId, $langcode) {
		$db = DBHandler::dbGet();
		if (! is_numeric($articleId)) {
			$msg = "removing article_boxcontentlist_connect records article_id=$articleId,langcode=$langcode from db failed: id is not a number";
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);
			throw new Exception(TextHandler::getText("ear_err_boxcontentconnectdeletefailed"));
		}

		if (is_null($langcode)) {
			$statement = $db->prepare("delete from article_boxcontentlist_connect where article_id=?");
			$data = array($articleId);
		} else {
			$statement = $db->prepare("delete from article_boxcontentlist_connect where article_id=? and langcode=?");
			$data = array($articleId, $langcode);
		}
		$result =& $db->execute($statement, $data);
			
		if (PEAR::isError($result))
		{
			$msg = "removing article_boxcontentlist_connect records article_id=$articleId,langcode=$langcode from db failed: ".$result->getDebugInfo();
			Log::error($msg);
			MailHelper::sendAdminMail("db error occured", $msg);
			throw new Exception(TextHandler::getText("ear_err_boxcontentconnectdeletefailed"));
		}
	}

	/* Versenyformák */

	/**
	 * Visszaadja a versenyformát.
	 *
	 * @param int $id Versenyforma azonosítója.
	 * @param string $langcode Ennek a nyelvkódnak megfelelően.
	 * @param boolean $any Ha nincs fordítás a rekordhoz, akkor is visszaad értékeket, ha más nyelven van.
	 */
	public static function getTournamentType($id, $langcode, $any = false) {
		$filter = new DBQueryFilter();
		$filter->addComponent('id', DBQueryFilter::OP_EQUALS, $id);
		if (! $any) {
			$filter->addComponent('langcode', DBQueryFilter::OP_EQUALS, $langcode);
			return GeneralDBHelper::getTableRowFiltered('tournamenttype', $filter);
		} else {
			$all = GeneralDBHelper::getTableRowsFiltered('tournamenttype', $filter);
			$result = array();
			foreach ($all as $record) {
				$result[$record['langcode']] = $record;
			}
			if (isset($result[$langcode])) {
				return $result[$langcode];
			} else if (isset($result[AdminBase::getCurrentEditlang()])) {
				return $result[AdminBase::getCurrentEditlang()];
			} else if (isset($result[AdminBase::getDefaultEditlang()])) {
				return $result[AdminBase::getDefaultEditlang()];
			} else if (count($result) > 0) {
				return $result[0];
			} else {
				$result = null;
				return $result;
			}
		}
	}

	/**
	 * Visszaadja a versenyformákat.
	 *
	 * @param string $langcode Ennek a nyelvkódnak megfelelően.
	 * @param boolean $all Minden versenyformát visszaad, még akkor is, ha nincs hozzá fordítás.
	 */
	public static function getTournamentTypes($langcode, $all = true) {
		if (! $all) {
			$filter = new DBQueryFilter();
			$filter->addComponent('langcode', DBQueryFilter::OP_EQUALS, $langcode);
			return GeneralDBHelper::getTableRowsFiltered('tournamenttype', $filter, array('name asc'));
		} else {
			$all = GeneralDBHelper::getTableRows('tournamenttype', array('id asc'));
			$result = array();
			foreach ($all as $record) {
				$found = ($record['langcode'] == $langcode);
				if (! $found) $found = ! isset($result[$record['id']]);
				if (! $found) $found = ($result[$record['id']]['langcode'] != $langcode && $record['langcode'] = TextHandler::getCurrentLangcode());
				if ($found) $result[$record['id']] = $record;
			}
			return $result;
		}
	}

	public static function addTournamentType($values) {
		$defaultValues = array("name" => $values['newname'], 'langcode' => AdminBase::getCurrentEditlang());
		return GeneralDBHelper::addTableRow('tournamenttype', $defaultValues);
	}

	public static function modTournamentType($values) {
		$values['langcode'] = AdminBase::getCurrentEditlang();
		$filter = new DBQueryFilter();
		$filter->addComponent('langcode', DBQueryFilter::OP_EQUALS, $values['langcode']);
		$filter->addComponent('id', DBQueryFilter::OP_EQUALS, $values['id']);
		$record = GeneralDBHelper::getTableRowFiltered('tournamenttype', $filter);
		if (! is_null($record)) {
			return GeneralDBHelper::modTableRowUsingFilter('tournamenttype', $values, $filter);
		} else {
			GeneralDBHelper::addTableRow('tournamenttype', $values, true);
			return $values;
		}
	}

	public static function delTournamentType($id) {
		return GeneralDBHelper::delTableRow('tournamenttype', $id);
	}

	/* Versenyek */

	/**
	 * Visszaadja a versenyeket.
	 *
	 * @param string $langcode Ennek a nyelvkódnak megfelelően.
	 * @param boolean $all Minden versenyt visszaad, még akkor is, ha nincs hozzá fordítás.
	 */
	public static function getTournaments($langcode, $all = true) {
		if (! $all) {
			$filter = new DBQueryFilter();
			$filter->addComponent('langcode', DBQueryFilter::OP_EQUALS, $langcode);
			return GeneralDBHelper::getTableRowsFiltered('vw_tournament', $filter, array('date_from desc'));
		} else {
			$all = GeneralDBHelper::getTableRows('vw_tournament', array('id asc'));
			$result = array();
			foreach ($all as $record) {
				$found = ($record['langcode'] == $langcode);
				if (! $found) $found = ! isset($result[$record['id']]);
				if (! $found) $found = ($result[$record['id']]['langcode'] != $langcode && $record['langcode'] = TextHandler::getCurrentLangcode());
				if ($found) $result[$record['id']] = $record;
			}
			if (! empty($result)) {
				// rendezés
				usort($result, array('AdminDBHelper', 'dateFromComparator'));
			}
			return $result;
		}
	}

	/**
	 * Összehasonlítja két tömb 'date_from' kulcsú elemét lexikálisan.
	 *
	 * @param array $arr1
	 * @param array $arr2
	 */
	public static function dateFromComparator($arr1, $arr2) {
		return -1 * strcmp($arr1['date_from'], $arr2['date_from']);
	}

	public static function addTournament($values) {
		DBHandler::dbBeginTransaction();
		try {
			$defaultValues = array("date_from" => $values['newdatefrom'], 'date_to' => $values['newdateto'], 'deadline' => $values['newdatefrom'], 'email' => $values['newemail'], 'default_langcode' => $values['newdefault_langcode']);
			$id = GeneralDBHelper::addTableRow('tournament', $defaultValues);
			$defaultValues = array("id_tournament" => $id, "name" => $values['newname'], "location" => $values['newlocation'], 'langcode' => AdminBase::getCurrentEditlang());
			GeneralDBHelper::addTableRow('tournament_texts', $defaultValues);
			DBHandler::dbCommit();
			DBHandler::dbEndTransaction();
		} catch (Exception $e) {
			DBHandler::dbRollback();
			throw $e;
		}
	}

	public static function modTournament($values) {
		DBHandler::dbBeginTransaction();
		try {
			// nyelvfüggetlen adatok mentése
			$defaultValues = array("id" => $values['id'], "date_from" => $values['date_from'], 'date_to' => $values['date_to'], 'deadline' => $values['deadline'], 'email' => $values['email'], 'default_langcode' => $values['default_langcode'], 'configuration' => $values['configuration']);
			$id = GeneralDBHelper::modTableRow('tournament', $defaultValues);
			// verseny - versenyforma kapcsolótáblából adatok törlése
			$filter = new DBQueryFilter();
			$filter->addComponent('id_tournament', DBQueryFilter::OP_EQUALS, $values['id']);
			GeneralDBHelper::delTableRowsFiltered('tournament_ttype', $filter);
			// nyelvfüggő dolgok mentése
			$filter->addComponent('langcode', DBQueryFilter::OP_EQUALS, AdminBase::getCurrentEditlang());
			$defaultValues = array("name" => $values['name'], "location" => $values['location']);
			try {
				GeneralDBHelper::modTableRowUsingFilter('tournament_texts', $defaultValues, $filter);
			} catch (MissingTableRowException $e) {
				// no language version: insert
				$defaultValues['id_tournament'] = $values['id'];
				$defaultValues['langcode'] = AdminBase::getCurrentEditlang();
				GeneralDBHelper::addTableRow('tournament_texts', $defaultValues);
			}
			// verseny - versenyforma kapcsolótáblába adatok mentése
			$defaultValues = array("id_tournament" => $values['id']);
			foreach ($values['types'] as $typeId) {
				$defaultValues['id_tournamenttype'] = $typeId;
				GeneralDBHelper::addTableRow('tournament_ttype', $defaultValues, true);
			}

			DBHandler::dbCommit();
			DBHandler::dbEndTransaction();
		} catch (Exception $e) {
			DBHandler::dbRollback();
			throw $e;
		}
	}

	public static function delTournament($id) {
		return GeneralDBHelper::delTableRow('tournament', $id);
	}

	/* Versenyhez cikkek */

	public static function addTournamentArticle($values) {
		GeneralDBHelper::addTableRow('tournament_article', $values, true);
	}

	public static function delTournamentArticle($tournamentId, $articleId) {
		$filter = new DBQueryFilter();
		$filter->addComponent('id_tournament', DBQueryFilter::OP_EQUALS, $tournamentId);
		$filter->addComponent('id_article', DBQueryFilter::OP_EQUALS, $articleId);
		return GeneralDBHelper::delTableRowsFiltered('tournament_article', $filter);
	}

	public static function defaultTournamentArticle($tournamentId, $articleId) {
		DBHandler::dbBeginTransaction();
		try {
			$filter = new DBQueryFilter();
			$filter->addComponent('id_tournament', DBQueryFilter::OP_EQUALS, $tournamentId);
			$defaultValues = array("isdefault" => 0);
			$id = GeneralDBHelper::modTableRowsUsingFilter('tournament_article', $defaultValues, $filter);
			$filter->addComponent('id_article', DBQueryFilter::OP_EQUALS, $articleId);
			$defaultValues = array("isdefault" => 1);
			GeneralDBHelper::modTableRowUsingFilter('tournament_article', $defaultValues, $filter);
			DBHandler::dbCommit();
			DBHandler::dbEndTransaction();
		} catch (Exception $e) {
			DBHandler::dbRollback();
			throw $e;
		}
	}

	/* Versenyhez jelentkezések */

	/**
	 * Pár/csapat jelentkezésének törlése.
	 * @param int $id Jelentkezés azonosító.
	 */
	public static function delTournamentRegistration($id) {
		return GeneralDBHelper::delTableRow('registration', $id);
	}

	public static function addTournamentRegistrationPlayer($defaultValues) {
		return GeneralDBHelper::addTableRow('registration_player', $defaultValues);
	}

	/**
	 * A pár egy tagjának, vagy a csapat egy tagjának törlése.
	 * @param int $id Játékos jelentkezésének azonosítója.
	 */
	public static function delTournamentRegistrationPlayer($id) {
		return GeneralDBHelper::delTableRow('registration_player', $id);
	}

	public static function modTournamentRegistrationPlayer($values) {
		return GeneralDBHelper::modTableRow('registration_player', $values);
	}

	/**
	 * Visszaadja a jelentkezést (minden játékost).
	 *
	 * @param int $id Jelentkezés azonosítója.
	 */
	public static function getTournamentRegistration($id, $needEmail = true) {
		$filter = new DBQueryFilter();
		$filter->addComponent('id', DBQueryFilter::OP_EQUALS, $id);
		$all = GeneralDBHelper::getTableRowsFiltered('vw_registration', $filter);
		$result = array();
		$currentRecord = null;
		foreach ($all as $record) {
			if (is_null($currentRecord) || $currentRecord['id'] != $record['id']) {
				if (! is_null($currentRecord)) {
					$result[] = $currentRecord;
				}
				$currentRecord = $record;
				$currentRecord['players'] = array();
				$currentRecord['emails'] = array();
			}
			$playerString = $record['name'];
			if (! empty($record['email']) && $needEmail) {
				$playerString .= ' ('.$record['email'].')';
				$currentRecord['emails'][] = $record['email'];
			}
			$currentRecord['players'][] = $playerString;
		}
		if (! is_null($currentRecord)) {
			$result[] = $currentRecord;
		}
		return $result;
	}

	/**
	 * Visszaadja a játékosok jelentkezéseit.
	 *
	 * @param int $tournamentId Verseny azonosítója.
	 * @param int $tournamentTypeId Verseny típus azonosítója.
	 */
	public static function getTournamentRegistrationPlayers($tournamentId, $tournamentTypeId, $orderBy = null) {
		$filter = new DBQueryFilter();
		$filter->addComponent('id_tournament', DBQueryFilter::OP_EQUALS, $tournamentId);
		$filter->addComponent('id_tournamenttype', DBQueryFilter::OP_EQUALS, $tournamentTypeId);
		$result = GeneralDBHelper::getTableRowsFiltered('vw_registration', $filter, $orderBy);
		return $result;
	}

	/**
	 * Visszaadja a játékos jelentkezését.
	 *
	 * @param int $id Jelentkezés azonosítója.
	 */
	public static function getTournamentRegistrationPlayer($id) {
		return GeneralDBHelper::getTableRow('registration_player', $id);
	}

	/**
	 * Visszaadja a játékos jelentkezés azonosító alapján a regisztrációs adatait.
	 *
	 * @param int $id Jelentkezés azonosítója.
	 */
	public static function getRegistrationByPlayerId($id) {
		$filter = new DBQueryFilter();
		$filter->addComponent('player_id', DBQueryFilter::OP_EQUALS, $id);
		$result = GeneralDBHelper::getTableRowFiltered('vw_registration', $filter);
		if (! empty($result)) {
			return $result;
		} else {
			return null;
		}
	}

}
